﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine;
using Engine.Attributes;

namespace Engine.Components.Architecture
{
	public class MemoryBank
	{
		private byte[] memory;

		/// <summary>
		/// Sets the address of a byte to be read or written
		/// </summary>
		[InPort]
		public int Address { private get;  set; }

		/// <summary>
		/// Data available to be written
		/// </summary>
		[InPort]
		public int WriteData { private get; set; }

		/// <summary>
		/// Set to true if data is to be written; false if data is to be read
		/// </summary>
		[InPort]
		public bool WriteFlag { private get; set; }

		/// <summary>
		/// Data available to be read
		/// </summary>
		[OutPort]
		public byte ReadData { get; private set;  }

		/// <summary>
		/// Returns the size, in bytes, of the memory
		/// </summary>
		[Config]
		public int SizeInBytes
		{
			get { return this.memory.Length; }
			set { this.memory = new byte[value]; }
		}

		/// <summary>
		/// Creates a MemoryBank Component with a default size of 4096 bytes.
		/// </summary>
		public MemoryBank()
		{
			this.SizeInBytes = 4096;
		}

		public void Run()
		{
			// valid address check
			if (Address < 0 || Address >= memory.Length)
			{
				throw new Exception("Address out of range.  Minimum allowed is 0, maximum allowed is " + SizeInBytes.ToString());
			}

			if (WriteFlag) // data to be written
			{
				memory[Address] = WriteData;
			}
			else // data to be read
			{
				ReadData = memory[Address];
			}
		}
	}
}
